#ifndef BVH_DEBUG_TRACER_H
#define BVH_DEBUG_TRACER_H

#include "../RayTracePro/RayTracePro.h"

namespace RayTracePro
{
	template<typename T, typename Tracer, bool pred>
	bool TraverseBvhDbg(RayTraceSystem * system, const Tracer & tracer, DifferentialGeometry & rs, Bvh<T> & tree, const Ray & ray, const RayDifferential & rayDiff, float & t,
		Array<int, true> & traversedNodes)
	{
#ifdef PROFILE_BVH
		int leavesTraversed = 0, nodesTraversed = 0, trianglesTested = 0, hits = 0;
#endif
		bool hit = false;
		Vec3 origin;
		Vec3::Scale(origin, ray.Direction, ray.tMin);
		Vec3::Add(origin, origin, ray.Origin);
		float tmax = ray.tMax;
		int dirIsNeg[3] = { ray.ReciprocalDirection.x < 0, ray.ReciprocalDirection.y < 0, ray.ReciprocalDirection.z < 0 };
		BvhNode* node = tree.Nodes.Buffer();
		int todoOffset = 0;
		BvhNode* todo[64];
		auto traceRay = ray;
		while (true)
		{
			IntPtr nodeId = node - tree.Nodes.Buffer();
			if (nodeId == 2)
				nodeId = 0;
			float t1,t2;
			if (RayBBoxIntersection(node->Bounds, ray, t1, t2, dirIsNeg) && t1<traceRay.tMax)
			{
				traversedNodes.Add((int)(node-tree.Nodes.Buffer()));
#ifdef PROFILE_BVH
				nodesTraversed++;
#endif
				if (node->ElementCount > 0)
				{
#ifdef PROFILE_BVH
					leavesTraversed++;
#endif
					DifferentialGeometry inter;
					inter.Init();

					for (int i = node->ElementId; i < node->ElementId+node->ElementCount; i++)
					{
#ifdef PROFILE_BVH
						trianglesTested++;
#endif
						if (tracer.Trace(inter, tree.Elements[i], traceRay, rayDiff, tmax))
						{
							if (pred)
								return true;	
							if (tmax <= traceRay.tMax)
							{
								rs = inter;
								traceRay.tMax = tmax;
								t = tmax;
								hit = true;
#ifdef PROFILE_BVH
								hits++;
#endif
							}
						}
					}
					if (todoOffset == 0) break;
					node = todo[--todoOffset];
				}
				else
				{
					if (ray.Origin[node->Axis] > (node + 1)->Bounds.Max[node->Axis])
					{
						todo[todoOffset++] = node + 1;
						node = node + node->ChildOffset;
					}
					else
					{
						todo[todoOffset++] = node + node->ChildOffset;
						node = node + 1;
					}
				}
			}
			else
			{
				if (todoOffset == 0)
					break;
				node = todo[--todoOffset];
			}
		}
#ifdef PROFILE_BVH
		system->BvhProfiler.AddRecord(leavesTraversed, nodesTraversed, trianglesTested, hits, 0);
#endif
		return hit;
	}
#endif
}